package com.terracloud.server.utils;

/**
 *
 * @author chenhainan
 * @since 2025/10/31
 */

import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Set;

/**
 * x509证书工具,用于生成x509证书
 *
 * @author chenhainan
 * @since 2023/9/15 11:27
 */
@Slf4j
public class X509Utils {

    /**
     * 当前项目位置,如果是根目录,就需要特殊处理一下
     */
    private static final String CURRENT_DIR = "/".equals(System.getProperty("user.dir")) ? "" : System.getProperty("user.dir");

    /**
     * 生成工具目录位置
     */
    private static final String TOOL_DIR = CURRENT_DIR + "/ssl-tools";

    /**
     * 生成工具位置
     */
    private static final String SHELL_PATH = TOOL_DIR + "/client.keygen.sh";

    /**
     * 配置文件位置
     */
    private static final String PROPERTIES_PATH = TOOL_DIR + "/keygen.properties";

    /**
     * 公钥文件名
     */
    private static final String CLIENT_CERTIFICATE_FILE_PATH = TOOL_DIR + "/client.pub.pem";

    /**
     * 私钥文件名
     */
    private static final String CLIENT_KEY_FILE_NAME = TOOL_DIR + "/client.nopass.pem";

    /**
     * 服务端公钥文件路径
     */
    private static final String SERVER_KEY_FILE_PATH = TOOL_DIR + "/mqttserver.pub.pem";

    private static final Set<String> ALL_FILE_NAME = Set.of("client.jks",
            "client.p12", "client.pem", "client.pk8.pem", "client.pub.pem");

    private X509Utils() {
    }


    /**
     * 密钥对写入文件,并打包成zip文件
     *
     * @return 密钥对文件
     * @throws IOException 异常
     */
    public static File buildKeyFile() throws IOException {
        final var commandArray = new String[]{SHELL_PATH, " -p ", TOOL_DIR};
        try (final var resultReader = new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec(commandArray, null,
                new File(CURRENT_DIR + "/ssl-tools")).getInputStream()));) {
            resultReader.lines().forEach(log::debug);
        }
        // 生成临时文件
        final var zipTempFile = File.createTempFile("device-cert", ".zip");
        final var certificatePemTempFile = new File(CLIENT_CERTIFICATE_FILE_PATH);
        final var keyPemTempFile = new File(CLIENT_KEY_FILE_NAME);
        // 打包
        try (final ZipFile zipFile = new ZipFile(zipTempFile)) {
            final var certificatePemZipParameters = new ZipParameters();
            certificatePemZipParameters.setFileNameInZip("client.pub.pem");
            zipFile.addFile(certificatePemTempFile, certificatePemZipParameters);
            final var keyPemZipParameters = new ZipParameters();
            keyPemZipParameters.setFileNameInZip("client.key.pem");
            zipFile.addFile(keyPemTempFile, keyPemZipParameters);
            final var servercertificatePemZipParameters = new ZipParameters();
            servercertificatePemZipParameters.setFileNameInZip("server.pub.pem");
            zipFile.addFile(new File(SERVER_KEY_FILE_PATH), servercertificatePemZipParameters);
        }
        ALL_FILE_NAME.forEach(fileName -> {
            try {
                Files.deleteIfExists(Paths.get(TOOL_DIR, fileName));
            } catch (IOException e) {
                log.error("删除临时文件失败", e);
            }
        });
        return zipTempFile;
    }


}
